#!/usr/bin/env python

import re
import os
import glob
from xml.dom.minidom import parse
from gurpsdata import Trait, Skill, Character

def list_characters(dirpath):
    if not os.path.isdir(dirpath):
        # TODO: raise a proper exception ('invalid character dir')
        raise Exception

    char_files = glob.glob(os.path.join(dirpath, '*.xml'))

    characters = []
    for cfname in char_files:
        cf = open(cfname, 'r')
        name = None
        points = None
        for line in cf:
            m = re.match('<character.*?name="(.*?)".*?', line)
            if m:
                name = m.group(1)

            m = re.match('<points.*?total="(.*?)".*?', line)
            if m:
                points = m.group(1)

            if name and points:
                characters.append((name, points, os.path.basename(cfname)))
                break

    return characters


def load_character(filename):
    try:
        doc = parse(filename)
    except:
        return None

    def process_attributes(node, char):
        for child in node.childNodes:
            if child.nodeType != node.ELEMENT_NODE:
                continue

            if child.nodeName == 'damage':
                char.__setattr__('damage_throw',
                                 child.getAttribute('throw'))
                char.__setattr__('damage_swing',
                                 child.getAttribute('swing'))
                continue

            elif child.nodeName == 'basicspeed':
                value = float(child.getAttribute('value'))
            else:
                value = int(child.getAttribute('value'))

            char.__setattr__(child.nodeName, value)

    def process_traits(node):
        traits = []
        for child in node.childNodes:
            if child.nodeType != node.ELEMENT_NODE:
                continue

            trait = Trait(child.getAttribute('name'))
            trait.ttype = child.getAttribute('type')
            try:
                trait.kind = child.getAttribute('kind')
            except:
                pass
            try:
                trait.level = int(child.getAttribute('level'))
            except:
                pass
            trait.cost = int(child.getAttribute('cost'))

            if child.hasChildNodes():
                trait.description = child.firstChild.wholeText.strip()

            traits.append(trait)

        return traits

    def process_skills(node):
        skills = []
        for child in node.childNodes:
            if child.nodeType != node.ELEMENT_NODE:
                continue

            skill = Skill(child.getAttribute('name'))
            skill.relativelevel = child.getAttribute('relativelevel')
            skill.level = int(child.getAttribute('level'))
            skill.cost = int(child.getAttribute('cost'))

            if child.hasChildNodes():
                skill.description = child.firstChild.wholeText.strip()

            skills.append(skill)

        return skills

    charsheet = doc.documentElement
    char = Character()

    char.__setattr__('name', charsheet.getAttribute('name'))
    char.__setattr__('player', charsheet.getAttribute('player'))
    char.__setattr__('created', charsheet.getAttribute('created'))

    for node in charsheet.childNodes:
        if node.nodeType != node.ELEMENT_NODE:
            continue

        if node.tagName == 'points':
            char.__setattr__('points_total',
                             int(node.getAttribute('total')))
            char.__setattr__('points_unspent',
                             int(node.getAttribute('unspent')))

        elif node.tagName == 'appearance':
            char.__setattr__('age', int(node.getAttribute('age')))
            char.__setattr__('height', node.getAttribute('height'))
            char.__setattr__('weight', node.getAttribute('weight'))
            char.__setattr__('sizemodifier',
                             int(node.getAttribute('sizemodifier')))
            if node.hasChildNodes():
               char.appearance = node.firstChild.wholeText.strip()

        elif node.tagName == 'attributes':
            process_attributes(node, char)

        elif node.tagName in ('advantages', 'disadvantages'):
            traits = process_traits(node)
            char.__setattr__(node.tagName, traits)

        elif node.tagName in ('skills', 'spells'):
            skills = process_skills(node)
            char.__setattr__(node.tagName, skills)

    return char


if __name__ == '__main__':
    c = load_character('pc.xml')
    print c

    print list_characters('/home/setanta/garden/setanta-labs/evas/gurps-tl9/data/')

